home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-09-17 | 53.5 KB | 2,048 lines | [TEXT/MPS ] |
- /*
- * This file has been changed from the original MacApp 3.1.1
- * to support the metrowerks CodeWarrior compilers C/C++ 1.1.1.
- * These changes are known *not* to work with earlier versions
- * of CodeWarrior. Every attempt though has been made to to keep
- * this file compatible with other development environments.
- *
- * Mark Anderson
- * metrowerks
- * 9/16/94
- *
- */
-
- //----------------------------------------------------------------------------------------
- // UMemory.cp
- // Copyright © 1985-1994 by Apple Computer, Inc. All rights reserved.
- //----------------------------------------------------------------------------------------
-
- #ifndef __UMEMORY__
- #include "UMemory.h"
- #endif
-
- #ifndef __STDIO__
- #include <stdio.h>
- #endif
-
- #ifndef __UFAILURE__
- #include "UFailure.h"
- #endif
-
- #ifndef __MEMORY__
- #include "Memory.h"
- #endif
-
- #ifndef __OBJECTHEAP__
- #include "ObjectHeap.h"
- #endif
-
- #ifndef __TEXTEDIT__
- #include "TextEdit.h"
- #endif
-
- #ifndef __OSUTILS__
- #include "OSUtils.h"
- #endif
-
- #ifndef __UMACAPPUTILITIES__
- #include "UMacAppUtilities.h"
- #endif
-
- #ifndef __TRAPS__
- #include "Traps.h"
- #endif
-
- #ifndef __DEVICES__
- #include "Devices.h"
- #endif
-
- #ifndef __TOOLUTILS__
- #include "ToolUtils.h"
- #endif
-
- #ifndef __RESOURCES__
- #include "Resources.h"
- #endif
-
- #ifndef __PACKAGES__
- #include "Packages.h"
- #endif
-
- #ifndef __ERRORS__
- #include "Errors.h"
- #endif
-
- #ifndef __UDEBUG__
- #include "UDebug.h"
- #endif
-
- #ifndef __SEGLOAD__
- #include "SegLoad.h"
- #endif
-
- #if qModelFarCode
- #ifndef __RTLIB__
- #include "RtLib.h"
- #endif
- #endif
-
- #if qDebugMsg
- #ifndef __STDIO__
- #include <stdio.h>
- #endif
- #endif
-
- #ifndef __LOWMEM__
- #include <LowMem.h>
- #endif
-
- //----------------------------------------------------------------------------------------
- // Globals to this module and externally available.
-
- ObjectHeap* gObjectHeap;
-
- Size gMaxLockedRsrc;
- HandleListHandle gSysMemList;
- HandleListHandle gApp1MemList;
- HandleListHandle gApp2MemList;
-
- short gCodeRefNum;
-
- #if !qPowerPC
- HandleListHandle gCodeSegs;
- BoolListHandle gIsLoadedSeg;
- BoolListHandle gIsResidentSeg;
- #endif
-
- // Used to be able to enable/disable the calculation of seg! resources in non-debug mode.
-
- Boolean gCheckRsrcUsage = false;
-
- // Static, globals to this module. Many of these are static by convention, but we don't
- // declare them as static because people may want to examine them.
-
- #if !qPowerPC
- Boolean gUnloadAllSegs;
- #endif
-
- UniversalProcPtr gGZPurgeNotify;
-
- #if !qPowerPC
- LongListHandle pSegSize;
- #endif
-
- Handle pCodeReserve;
- Handle pMemReserve;
- Boolean pOKCodeReserve;
- Boolean pPermAllocation;
- Boolean pReserveExists;
-
- #if qDebug
- long pReserveShortfall;
- #endif
-
- Size pSzCodeReserve;
- Size pSzMemReserve;
- TrapPatch pSegLoadPatch;
- short pOldResFile;
- Boolean pLoadSegCalledFromOwnApp;
-
- #if !qPowerPC
- short pMaxSegNum;
- #endif
-
- // local private globals
- static Boolean pDuringGrowZone;
- #if qModelFarCode
- static SegLoadHdlrPtr oldPreLoadHandler;
- static SegLoadHdlrPtr oldPostLoadHandler;
- #endif
-
- // Function prototypes for some routines in this module.
-
- pascal long GrowZoneProc(Size needed);
-
- // Function prototypes for the routines in UMemory.a
-
- #if !qPowerPC
- pascal void ALoadMacAppSeg();
- #endif
-
- // LoadSeg is Patched to call ALoadMacAppSeg, which in turn calls LoadMacAppSegment.
- // ALoadMacAppSeg can only be referenced as a procedure pointer, because no args are
- // declared
-
- typedef pascal void (*NotifyType)(Handle h);
-
- #if qModelFarCode
- typedef pascal short (*HandlerType)(RTState* state);
- #endif
-
-
- //----------------------------------------------------------------------------------------
- //----------------------------------------------------------------------------------------
- //----------------------------------------------------------------------------------------
-
-
- //----------------------------------------------------------------------------------------
-
- // These "MAFoo" functions were originally for THINK Pascal compatibility (but useful in the
- // larger problem of multiple open resource maps in general); when running under the THINK
- // environment, CODE resources are not found in the same resource file as other
- // application resources, so a UseResFile call needs to be made to bring the project
- // resource file into the search path. "gCodeRefNum" is set up at initialization time.
-
- //----------------------------------------------------------------------------------------
-
-
- //----------------------------------------------------------------------------------------
- // MAGet1Resource:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Handle MAGet1Resource(ResType rType, short rID)
- {
- short oldResFile;
- Handle resource;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- resource = Get1Resource(rType, rID);
- MAUseResFile(oldResFile);
-
- return resource;
- } // MAGet1Resource
-
- //----------------------------------------------------------------------------------------
- // MAGet1NamedResource:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Handle MAGet1NamedResource(ResType rType, const CStr255 &name)
- {
- short oldResFile;
- Handle namedResource;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- namedResource = Get1NamedResource(rType, name);
- MAUseResFile(oldResFile);
-
- return namedResource;
- } // MAGet1NamedResource
-
- //----------------------------------------------------------------------------------------
- // MAGet1IndResource:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Handle MAGet1IndResource(ResType rType, short index)
- {
- short oldResFile;
- Handle indResource;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- indResource = Get1IndResource(rType, index);
- MAUseResFile(oldResFile);
-
- return indResource;
- } // MAGet1IndResource
-
- //----------------------------------------------------------------------------------------
- // MACount1Resources:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- short MACount1Resources(ResType rType)
- {
- short oldResFile;
- short resourceCnt;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- resourceCnt = Count1Resources(rType);
- MAUseResFile(oldResFile);
-
- return resourceCnt;
- } // MACount1Resources
-
- //----------------------------------------------------------------------------------------
- // MAGetResource:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Handle MAGetResource(ResType rType, short rID)
- {
- Handle h;
- short oldResFile;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- h = GetResource(rType, rID);
- MAUseResFile(oldResFile);
-
- return h;
- } // MAGetResource
-
- //----------------------------------------------------------------------------------------
- // MAGetNamedResource:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Handle MAGetNamedResource(ResType rType, const CStr255 &name)
- {
- Handle h;
- short oldResFile;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- h = GetNamedResource(rType, name);
- MAUseResFile(oldResFile);
-
- return h;
- } // MAGetNamedResource
-
- //----------------------------------------------------------------------------------------
- // MAGetIndResource:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Handle MAGetIndResource(ResType rType, short index)
- {
- Handle h;
- short oldResFile;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- h = GetIndResource(rType, index);
- MAUseResFile(oldResFile);
-
- return h;
- } // MAGetIndResource
-
- //----------------------------------------------------------------------------------------
- // MACountResources:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- short MACountResources(ResType rType)
- {
- short oldResFile;
- short resourceCnt;
-
- oldResFile = MAUseResFile(gCodeRefNum);
- resourceCnt = CountResources(rType);
- MAUseResFile(oldResFile);
-
- return resourceCnt;
- } // MACountResources
-
- //----------------------------------------------------------------------------------------
- // GetSegResource:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Handle GetSegResource(short segnum)
- {
- return MAGet1Resource(kCode, segnum);
- } // GetSegResource
-
- //----------------------------------------------------------------------------------------
- // AddAllRsrc:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- void AddAllRsrc(ResType rType, HandleListHandle toList)
- {
- short oldResLoad = LMGetResLoad();
- SetResLoad(false);
-
- short nResources = CountResources(rType);
- for (short i = 1; i <= nResources; ++i)
- {
- short theID;
- Handle h;
- ResType theType;
- Str255 theName;
-
- h = GetIndResource(rType, i);
- GetResInfo(h, &theID, &theType, theName);
-
- // If there is a ROM resource for this type and ID, don't put it
- // on the list since it will not consume any memory.
-
- UseROMMap(false);
- h = GetResource(rType, theID);
- UseROMMap(true);
- if ((h) && (HomeResFile(h) != 1))
- AddHandle(h, toList);
- }
-
- SetResLoad(oldResLoad);
- } // AddAllRsrc
-
- //----------------------------------------------------------------------------------------
- // AddHandle:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- void AddHandle(Handle h, HandleListHandle toList)
- {
- long offset;
-
- offset = Munger((Handle)toList, 0, NULL, 0, &h, 4);
- FailMemError();
- } // AddHandle
-
- //----------------------------------------------------------------------------------------
- // AddSegSizes:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- Size AddSegSizes(Handle segRsrc)
- {
- SignedByte savedState;
- SignedBytePtr p;
- short oldResLoad;
- register long total;
- Handle seg;
- short i;
- CStr255 s;
-
- savedState = LockHandleHigh(segRsrc);
-
- oldResLoad = LMGetResLoad();
- SetResLoad(false);
-
- p = (SignedBytePtr) * segRsrc;
- i = *((IntegerPtr)p);
- p += 2;
-
- total = 0;
-
- for (; i > 0; i--, p += *p + 1)
- {
- BlockMove(p, &s, *p + 1);
- seg = MAGet1NamedResource(kCode, s);
- if (seg)
- total += GetResourceSizeOnDisk(seg) + 8;
- }
-
- SetResLoad(oldResLoad);
- HSetState(segRsrc, savedState);
-
- return total;
- } // AddSegSizes
-
- //----------------------------------------------------------------------------------------
- // IsHandleEligible:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Boolean IsHandleEligible(Handle h)
- {
- if (h == NULL)
- return false; // Thanks Pillar!
- else if (IsHandlePurged(h))
- return false;
- else
- return (h != LMGetGZMoveHnd()) && (h != LMGetGZRootHnd());
- } // IsHandleEligible
-
- //----------------------------------------------------------------------------------------
- // BuildCodeReserve:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- void BuildCodeReserve(Size allocLim, Boolean fromGZ)
- {
- static const short initVal = 0xF7;
-
- Size needed, avail;
- Handle canPurge = 0;
- #if qDebug
- Size theSize;
- #endif
-
- pOKCodeReserve = true; // default value
-
- #if qDebug
- pReserveShortfall = 0;
-
- if (!pPermAllocation)
- ProgramBreak("BuildCodeReserve called with pPermAllocation = false");
- #endif
-
- if (!pReserveExists)
- {
- // free the current code reserve
- if (IsHandleEligible(pCodeReserve))
- {
- EmptyHandle(pCodeReserve);
- pReserveExists = false;
- }
-
- // compute amt actually needed
- needed = Min(pSzCodeReserve - TotalTempSize(false, canPurge) - 8, allocLim);
-
- if (needed > 0)
- {
- // make as much memory available as possible
- if (IsHandleEligible(pMemReserve))
- EmptyHandle(pMemReserve);
-
- if (fromGZ) // Never purge or compact from GrowZone
- avail = allocLim;
- else
- {
- PurgeMem(needed);
- avail = CompactMem(needed);
- }
-
- if (avail < needed) // could not get the whole reserve
- {
- #if qDebug
- pReserveShortfall = needed - avail;
- #endif
-
- pOKCodeReserve = false;
- pReserveExists = false;
-
- needed = avail; // get the most we can
- }
-
- #if !qPowerPC
- if (!fromGZ && (IsHandlePurged(pCodeReserve) || IsHandleEligible(pCodeReserve)))
- {
- ReallocateHandle(pCodeReserve, needed);
- if (MemError() == noErr)
- pReserveExists = true;
- }
-
- #if qDebug
- theSize = GetHandleSize(pCodeReserve);
- if (theSize != 0)
- BlockSet(*pCodeReserve, theSize, initVal);
- #endif
-
- if (!IsHandlePurged(pCodeReserve))
- {
- // Large handles are almost as bad as nonrelocatable blocks. Try to get
- // this guy out of the way, just in case.
-
- if (!fromGZ)
- MoveHHi(pCodeReserve);
- }
- #endif // if !qPowerPC
- }
- }
- } // BuildCodeReserve
-
- //----------------------------------------------------------------------------------------
- // BuildAllReserves:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- void BuildAllReserves()
- {
- static const short initVal = 0xF7;
-
- Boolean oldPerm;
- #if qDebug
- Size theSize;
- #endif
-
- // set the permanent flag to ensure that the code reserve is actually allocated and
- // not given up to the low space reserve
-
- oldPerm = pPermAllocation;
- pPermAllocation = true;
-
- BuildCodeReserve(kGZMaxAlloc, false); // make sure code reserve is OK
-
- // reallocate the low space handle, if necessary
-
- if (IsHandlePurged(pMemReserve))
- {
- ReallocateHandle(pMemReserve, pSzMemReserve);
- #if qDebug
- theSize = GetHandleSize(pMemReserve);
- if (theSize != 0)
- BlockSet(*pMemReserve, theSize, initVal);
- #endif
-
- }
-
- pPermAllocation = oldPerm; // reset the permanent flag
- } // BuildAllReserves
-
- //----------------------------------------------------------------------------------------
- // CheckReserve:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Boolean CheckReserve()
- {
- BuildAllReserves();
- return pOKCodeReserve;
- } // CheckReserve
-
- //----------------------------------------------------------------------------------------
- // CheckRsrcUsage:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- void CheckRsrcUsage()
- {
- long sz;
- Handle h;
- CStr255 s;
-
- sz = TotalTempSize(true, h);
- if (sz > gMaxLockedRsrc)
- {
- // In non debug mode, one can calculate seg! resources by loading the application
- // under SADE, setting the variable gCheckRsrcUsage to true, and setting a break
- // point on the following line. Everytime SADE breaks on this line, you can use
- // the heap command to look at your loaded segments.
-
- gMaxLockedRsrc = sz;
-
- #if qDebug
- if (gRsrcReport)
- {
- ShowSegments();
- NumToString(gMaxLockedRsrc, s);
- s = " = New maximum resources usage: " + s + " =";
- ProgramReport(s, gMemMgtBreak);
- }
- #endif
-
- }
- } // CheckRsrcUsage
-
- //----------------------------------------------------------------------------------------
- // DoInitUMemory: Called from InitUMemory so that InitUMemory can be in the main segment
- // and this code can be in another (unloadable) segment.
- //----------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- void DoInitUMemory(Size &sizeObjectHeap,
- Size &sizeHeapIncrement,
- Size &sizeTempReserve,
- Size &sizeLowSpaceReserve)
- {
- #if defined(powerc) || defined (__powerc)
- #pragma options align=mac68k
- #endif
- struct Mem
- {
- long objectHeap, heapIncrement, codeVal, lowSpaceVal, stackVal;
- };
- #if defined(powerc) || defined(__powerc)
- #pragma options align=reset
- #endif
-
- typedef Mem *MemPtr,
- **MemHandle;
-
- short i,
- rsrcCnt;
- short oldResLoad;
- Handle seg, h;
- long stackTot;
- short rsrcID;
- ResType rsrcType;
- Str255 rsrcName;
- short lastRsrc;
- short mainSegment, utilitySegment;
-
- // Initialize memory management globals
-
- pPermAllocation = false;
- pMemReserve = NewHandle(0);
- FailNIL(pMemReserve);
-
- pSzMemReserve = 0;
- pCodeReserve = NewHandle(0);
- FailNIL(pCodeReserve);
-
- pSzCodeReserve = 0;
- gGZPurgeNotify = NULL;
- pOKCodeReserve = true;
- pReserveExists = false;
-
- #if !qPowerPC
- gUnloadAllSegs = true;
- #endif
-
- gCodeRefNum = LMGetCurApRefNum();
-
- #if !qPowerPC
- pMaxSegNum = 0;
-
- //###########################################
- // No resource loading
-
- oldResLoad = LMGetResLoad();
- SetResLoad(false);
-
- // Figure the highest segment number
- lastRsrc = MACount1Resources(kCode);
-
- // some development systems may not have contiguous numbering of CODE segments. try to
- // be polite about handling it
-
- for (i = 1; i <= lastRsrc; ++i)
- {
- seg = MAGet1IndResource(kCode, i);
-
- // we only have an index find the real resource ID and keep track of the highest one
-
- if (seg)
- {
- GetResInfo(seg, &rsrcID, &rsrcType, rsrcName);
- pMaxSegNum = (short)Max(rsrcID, pMaxSegNum);
- }
- }
-
- SetResLoad(oldResLoad); // in case of failure
-
- // Allocate the master segment lists.
- gCodeSegs = (HandleListHandle)NewHandle(pMaxSegNum * sizeof(Handle));
- FailNIL(gCodeSegs);
-
- gIsResidentSeg = (BoolListHandle)NewHandle(pMaxSegNum * sizeof(Boolean));
- FailNIL(gIsResidentSeg);
-
- gIsLoadedSeg = (BoolListHandle)NewHandle(pMaxSegNum * sizeof(Boolean));
- FailNIL(gIsLoadedSeg);
-
- /* (NOTE: assumes application doesn't change the CODE segment size at runtime
- (a very safe assumption)). Used in GetSegFromPC. */
-
- pSegSize = (LongListHandle)NewHandle(pMaxSegNum * sizeof(long));
- FailNIL(pSegSize);
-
- oldResLoad = LMGetResLoad(); // OK, suppress segment loading again
- SetResLoad(false);
-
- // Segments and their sizes and actual loaded state (helps catch preloads)
-
- for (i = 0; i < pMaxSegNum; ++i)
- {
- (*gIsResidentSeg)[i] = false;
- seg = GetSegResource(i + 1);
- (*gCodeSegs)[i] = seg;
- if (seg) // seg is non-nil if the segment number
- (*pSegSize)[i] = GetResourceSizeOnDisk(seg);
- else
- (*pSegSize)[i] = 0;
-
- (*gIsLoadedSeg)[i] = true; // Assume all segments are loaded
- }
-
- SetResLoad(oldResLoad);
- //###########################################
-
- mainSegment = GetSegNumber((ProcPtr) & InitUMemory);// Main is always resident
- (*gIsResidentSeg)[mainSegment - 1] = true;
-
- utilitySegment = GetSegNumber((ProcPtr) & UnloadAllSegments);// Utilities are always resident
- (*gIsResidentSeg)[utilitySegment - 1] = true;
-
- #ifdef __MWERKS__ // __%Main must be resident
- (*gIsResidentSeg)[0] = true;
- #endif
-
- #if qModelFarCode
-
- // (*gIsResidentSeg)[pMaxSegNum - 1] = true; // 32-bit bootstrap is always last
- // _AND_ resident
- // THIS IS NOT TRUE. With ILink,
- // 32-bit bootstrap is segment 2.
-
- {
- CStr255 name("32-bit bootstrap");
- Handle seg = MAGet1NamedResource(kCode, name);
- if (seg)
- {
- short segnum;
- ResType theType;
-
- GetResInfo(seg, &segnum, &theType, name);
- (*gIsResidentSeg)[segnum - 1] = true;
- }
- }
- #endif
- #endif
-
- // init the gSysMemList
-
- gSysMemList = (HandleListHandle)NewHandle(0);
- FailNIL(gSysMemList);
-
- AddAllRsrc('LDEF', gSysMemList);
- AddAllRsrc('CDEF', gSysMemList);
- AddAllRsrc('MDEF', gSysMemList);
- AddAllRsrc('WDEF', gSysMemList);
- AddAllRsrc('PACK', gSysMemList);
-
- // Compute memory slop needed
-
- sizeObjectHeap = 0;
- sizeHeapIncrement = 0;
- sizeTempReserve = 0;
- sizeLowSpaceReserve = 0;
- stackTot = 0;
-
- #if !qPowerPC
- rsrcCnt = CountResources('seg!');
- for (i = 1; i <= rsrcCnt; ++i)
- {
- h = GetIndResource('seg!', i);
- sizeTempReserve += AddSegSizes(h);
- ReleaseResource(h);
- }
- #endif
-
- // Sum up the standard memory requirements
-
- rsrcCnt = CountResources('mem!');
- for (i = 1; i <= rsrcCnt; ++i)
- {
- h = GetIndResource('mem!', i);
- {
- const Mem &memH = **((MemHandle)h);
-
- sizeObjectHeap += memH.objectHeap;
- sizeHeapIncrement += memH.heapIncrement;
- sizeTempReserve += memH.codeVal;
- sizeLowSpaceReserve += memH.lowSpaceVal;
- stackTot += memH.stackVal;
- }
- ReleaseResource(h);
- }
-
- // Add on the processor dependent memory requirements
-
- #if qPowerPC
- const ResType kCPUmemResType = 'ppc!';
- #else
- const ResType kCPUmemResType = '68k!';
- #endif
-
- rsrcCnt = CountResources(kCPUmemResType);
- for (i = 1; i <= rsrcCnt; ++i)
- {
- h = GetIndResource(kCPUmemResType, i);
- {
- const Mem &memH = **((MemHandle)h);
-
- sizeObjectHeap += memH.objectHeap;
- sizeHeapIncrement += memH.heapIncrement;
- sizeTempReserve += memH.codeVal;
- sizeLowSpaceReserve += memH.lowSpaceVal;
- stackTot += memH.stackVal;
- }
- ReleaseResource(h);
- }
-
- SetStackSpace(stackTot);
-
- MaxApplZone();
-
- gApp1MemList = NULL;
- gApp2MemList = NULL;
-
- } // DoInitUMemory
-
- //----------------------------------------------------------------------------------------
- // FailNoReserve:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- void FailNoReserve()
- {
- if (!CheckReserve())
- Failure(memFullErr, 0);
- } // FailNoReserve
-
- //----------------------------------------------------------------------------------------
- // FailSpaceIsLow:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- void FailSpaceIsLow()
- {
- if (MemSpaceIsLow())
- Failure(memFullErr, 0);
- } // FailSpaceIsLow
-
- //----------------------------------------------------------------------------------------
- // GetReserveSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- void GetReserveSize(Size &szCodeReserve, Size &szMemReserve)
- {
- szCodeReserve = pSzCodeReserve;
- szMemReserve = pSzMemReserve;
- } // GetReserveSize
-
- //----------------------------------------------------------------------------------------
- // GetSegFromPC:
- //----------------------------------------------------------------------------------------
- #if !qPowerPC
- #pragma segment MAMemoryRes
-
- // Shouldn't be unloaded
-
- short GetSegFromPC(void* pc)
- {
- long segStart;
- short i;
- Handle seg;
-
- // Since GetSegFromPC may be called before gCodeSegs is set up, we have to test if
- // gCodeSegs == NULL before using it.
-
- if (gCodeSegs)
- for (i = 0; i < pMaxSegNum; ++i)
- {
- seg = (*gCodeSegs)[i]; // get segment handle
- if ((seg) &&!IsHandlePurged(seg)) // it's in memory
- {
- segStart = StripLong(*seg); // get segment start
- if (((long) pc >= segStart) && ((long) pc < segStart + (*pSegSize)[i]))
- return i + 1;
- }
- }
-
- return 0; // default return
- } // GetSegFromPC
- #endif
-
- #if !qPowerPC
- #if qModelFarCode
-
- //----------------------------------------------------------------------------------------
- // GetSegNumber: Gets seg number from a Jump table address.
- //
- // Must be in Main segment because we call this in order to make the resident segment
- // resident.
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- short GetSegNumber(ProcPtr aProc)
- {
- static const short kLoaded = 0x4EF9; // if loaded then a JMP instruction
- static const short kUnLoaded = 0xA9F0; // if unloaded then a _LoadSeg trap
-
- // Check for load and unloaded state, otherwise we are not pointing
- // at a valid jump table entry. In a model far jump table entry the first
- // two bytes are the segment number whether the segment is loaded or not.
-
- if (*((const short *)aProc) == kLoaded || *((const short *)aProc) == kUnLoaded)
- return *((const short *)((const char *)aProc - 2));
-
- #if qDebug
- ProgramBreak("GetSegNumber was not passed an jump table address");
- #endif
-
- return 0;
- } // GetSegNumber
-
- #else
-
- //----------------------------------------------------------------------------------------
- // GetSegNumber:
- //----------------------------------------------------------------------------------------
- short GetSegNumber(ProcPtr aProc)
- {
- static const short kLoaded = 0x4EF9; // if loaded then a JMP instruction
- #ifdef __MWERKS__
- static const short kUnLoaded = 0xA9F0; // if loaded then a JMP instruction
- const short offset = 6;
- #else
- static const short kUnLoaded = 0x3F3C; // if unloaded then a Move instruction (seg# onto stack)
- const short offset = 2;
- #endif
-
- if (*((const short *)aProc) == kLoaded) // loaded segment
- #ifdef __MWERKS__
- return *((const short *)((const char *) aProc + offset));
- #else
- return *((const short *)((const char *) aProc - offset));
- #endif
- else if (*((const short *)aProc) == kUnLoaded) // unloaded segment
- return *((const short *)((const char *) aProc + offset));
- else /* routine that computed &proc was in same
- segment as the proc */
- {
- #if qDebug
- ProgramBreak("GetSegNumber was not passed an jump table address");
- #endif
-
- return 0;
- }
- } // GetSegNumber
-
- #endif // qModelFarCode
- #endif // !qPowerPC
-
- //----------------------------------------------------------------------------------------
- // GetSegSize:
- //----------------------------------------------------------------------------------------
- #if !qPowerPC
- #pragma segment MAMemoryRes
-
- Size GetSegSize(short segnum)
- {
- return (*pSegSize)[segnum - 1];
- } // GetSegSize
- #endif
-
- //----------------------------------------------------------------------------------------
- // GrowZoneProc:
- //----------------------------------------------------------------------------------------
- #pragma push
- #pragma trace off
-
- #pragma segment MAMemoryRes
-
- pascal long GrowZoneProc(Size)
- {
- long result,
- reserveSize,
- OldA5;
- Handle canPurge;
- Size codeSize;
-
- OldA5 = SetCurrentA5(); // Can be called from other worlds
-
- result = 0; // default is to fail
-
- if (!pDuringGrowZone) // prevent re-entrancy
- {
- pDuringGrowZone = true;
-
- #if !qPowerPC
- // on a temp alloc, free all code slack immediately
-
- if (!pPermAllocation && IsHandleEligible(pCodeReserve))
- {
- EmptyHandle(pCodeReserve);
- pReserveExists = false;
- result = 1;
- }
-
- if (result == 0) // try harder: see if we can purge a code
- // segment or reduce the code reserve
- // handle
- {
- // compute size of resources currently in memory
-
- codeSize = TotalTempSize(false, canPurge);
-
- // see if the code reserve handle is too large
-
- if (IsHandleEligible(pCodeReserve))
- // we have a code reserve handle; this implies permanent allocation, otherwise
- // the handle would have been emptied above
- {
- reserveSize = GetHandleSize(pCodeReserve);
-
- // the following test is an optimization to avoid calling BuildCodeReserve
- // if there is no hope of reducing the code reserve handle
-
- if (codeSize + reserveSize + 8 > pSzCodeReserve)
- {
- // reserve is too big
- pReserveExists = false;
- // this should lower the code reserve
- BuildCodeReserve(reserveSize, true);
-
- // see if we succeeded in freeing some memory
- if (IsHandlePurged(pCodeReserve))
- result = 1;
- else if (GetHandleSize(pCodeReserve) < reserveSize)
- result = 1;
- }
- }
-
- // got something; only purge it if this is temporary || we know there is too
- // much code in memory already
-
- if ((result == 0) && (canPurge) && (!pPermAllocation || IsHandlePurged(pCodeReserve)))
- {
- if (gGZPurgeNotify)
- ((NotifyType)gGZPurgeNotify)(canPurge);
-
- reserveSize = GetHandleSize(canPurge);
- HPurge(canPurge);
- EmptyHandle(canPurge);
- pReserveExists = false;
-
- if (pPermAllocation) // don't free too much however
- BuildCodeReserve(reserveSize, true);
-
- result = 1;
- }
- }
- #endif // #if !qPowerPC
-
- // last ditch attempt-free emergency reserve
- if ((result == 0) && IsHandleEligible(pMemReserve))
- {
- EmptyHandle(pMemReserve);
- result = 1;
- }
-
- pDuringGrowZone = false;
- }
-
- OldA5 = SetA5(OldA5);
-
- return result;
- } // GrowZoneProc
-
- #pragma pop
-
- //----------------------------------------------------------------------------------------
- // InstallGrowZoneProc: Once called the grow zone proc's segment CANNOT be moved since
- // we're passing a NON-JT address to SetGrowZone (so we can be called from "other worlds"
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- // Must be in same segment as grow zone proc
-
- void InstallGrowZoneProc()
- {
- pDuringGrowZone = false;
-
- GrowZoneUPP gzUPP = NewGrowZoneProc(&GrowZoneProc);
- FailNIL(gzUPP);
- SetGrowZone(gzUPP);
- } // InstallGrowZoneProc
-
- //----------------------------------------------------------------------------------------
- // PreloadHandler:
- //----------------------------------------------------------------------------------------
- #if !qPowerPC
- #if qModelFarCode
- #pragma segment MAMemoryRes
-
- pascal short PreloadHandler(RTState* state)
-
- {
- LoadMacAppSegment(state->fSegNo);
-
- if (oldPreLoadHandler)
- return ((HandlerType)oldPreLoadHandler)(state);
- else
- return 0;
- } // PreloadHandler
- #endif
- #endif
-
- //----------------------------------------------------------------------------------------
- // PostLoadMacAppSegment:
- //----------------------------------------------------------------------------------------
- #if !qPowerPC
- #pragma push
- #pragma trace off
-
- #pragma segment MAMemoryRes
-
- // must be in Main segment
- // NOTE: this routine requires the pascal keyword because it is called from assembler
- // code that assumes pascal parameter passing conventions.
-
- pascal void PostLoadMacAppSegment()
- {
- long A5RegisterOnEntry = SetCurrentA5(); // ***** Called from trap patches *****
- // test if called from our application… if so, don't do patch behaviour. Thank you McSink!
- if (GetA5() == A5RegisterOnEntry && pLoadSegCalledFromOwnApp)
- MAUseResFile(pOldResFile); // Called back from our glue. Restores current res file pointer.
- SetA5(A5RegisterOnEntry);
- } // PostLoadMacAppSegment
-
- #pragma pop
- #endif
-
- //----------------------------------------------------------------------------------------
- // PostloadHandler:
- //----------------------------------------------------------------------------------------
- #if !qPowerPC
- #if qModelFarCode
- #pragma segment MAMemoryRes
-
- pascal short PostloadHandler(RTState* state)
-
- {
- PostLoadMacAppSegment();
- if (oldPostLoadHandler)
- return ((HandlerType)oldPostLoadHandler)(state);
- else
- return 0;
- } // PostloadHandler
- #endif
- #endif
-
- //----------------------------------------------------------------------------------------
- // InitUMemory:
- //----------------------------------------------------------------------------------------
- #pragma segment Main
- // Must be in main segment and called from main segment
-
- void InitUMemory(short callsToMoreMasters)
- {
- Size heapSize, heapIncrement, codeRes, lowSpaceRes = 0;
- THz applZone;
- short oldMoreMast;
-
- #if !qPowerPC
- // Get these segments out of the way so that when DoInitUMemory gets called and the
- // next block of master pointers gets allocated they won't constipate the heap
-
- Handle miniInitSeg = GetResource(kCode, GetSegNumber((ProcPtr) & DoInitUMemory));
- if (miniInitSeg)
- {
- UnloadSeg(&DoInitUMemory);
- LockHandleHigh(miniInitSeg);
- }
- #endif
-
- DoInitUMemory(heapSize, heapIncrement, codeRes, lowSpaceRes);
-
- #if !qPowerPC
- UnloadAllSegments(); // get init segment(s) out of middle of
- // heap, so SetReserveSize has maximum
- // space to work with
-
- if (miniInitSeg) // Yes, this would eventually get purged
- // if the space was needed badly enough,
- // but that happens very late in the game
- // and can confound the unwary
- EmptyHandle(miniInitSeg);
- #endif
-
- InstallGrowZoneProc();
-
- SetReserveSize(codeRes, lowSpaceRes);
- if (!pOKCodeReserve) // couldn't get code reserve. Can't
- { // continue
- Failure(memFullErr, 0);
- }
- else
- {
- #if !qPowerPC
- // Set up the LoadSeg patch
-
- #if qModelFarCode
- // Use the cool new RTLib so graciously
- // provided by Landon and Sandra
- RTPB anRTPB;
-
- // Install the preload handler
- anRTPB.fOperation = kRTSetPreLoad;
- anRTPB.fRTParam.fSegLoadParam.fUserHdlr = (SegLoadHdlrPtr) StripLong(PreloadHandler);
- if (Runtime(&anRTPB) != noErr)
- Failure(minErr, 0);
- oldPreLoadHandler = anRTPB.fRTParam.fSegLoadParam.fOldUserHdlr;
-
- // Install the postload handler
- anRTPB.fOperation = kRTSetPostLoad;
- anRTPB.fRTParam.fSegLoadParam.fUserHdlr = (SegLoadHdlrPtr) StripLong(PostloadHandler);
- if (Runtime(&anRTPB) != noErr)
- Failure(minErr, 0);
- oldPostLoadHandler = anRTPB.fRTParam.fSegLoadParam.fOldUserHdlr;
-
- pSegLoadPatch.LookupOldTrapAddress(_LoadSeg);
- #else
- FailOSErr(pSegLoadPatch.PatchTrap(_LoadSeg, ALoadMacAppSeg));
- #endif
- #endif
- }
-
- #if !qPowerPC
- UnloadAllSegments(); // unload one more time so memory is as clean as possible
- #endif
-
- // Here is a trick suggested by Jerome C.--it allocates one large block of master
- // pointers
- applZone = ApplicationZone();
- oldMoreMast = applZone->moreMast;
- long numMasterPointersDesired = oldMoreMast * callsToMoreMasters;
- do {
- applZone->moreMast = (short) Min(numMasterPointersDesired, kMaxShort);
- MoreMasters();
- numMasterPointersDesired -= applZone->moreMast;
- } while (numMasterPointersDesired > 0);
- applZone->moreMast = oldMoreMast;
-
- #if !qPowerPC
- LoadResidentSegments();
- #endif
-
- gUMemoryInitialized = true;
-
- // Now fully initialized, so create our pointer based heap for object allocation.
- // Now it will come out of permanent memory.
-
- if (gObjectHeap == NULL)
- {
- gObjectHeap = new ObjectHeap((size_t)heapSize, (size_t)heapIncrement);
- gObjectHeap->IObjectHeap();
- }
- else
- {
- gObjectHeap->ExpandHeap((size_t)heapSize, (size_t)heapIncrement);
- }
- } // InitUMemory
-
-
- //----------------------------------------------------------------------------------------
- // LoadMacAppSegment:
- //----------------------------------------------------------------------------------------
- #if !qPowerPC
- #pragma push
- #pragma trace off
-
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- pascal UniversalProcPtr LoadMacAppSegment(short segnum)
- {
- #if qDebug
- short id;
- ResType kind;
- CStr255 segName;
- MAName s;
- Handle seg;
- #endif
-
- long A5RegisterOnEntry = SetCurrentA5(); // ***** Called from trap patches *****
-
- UniversalProcPtr loadMacAppSegment = pSegLoadPatch.GetOldTrapAddr();// Where to go next
-
- if (GetA5() != A5RegisterOnEntry)
- {
- // not called from our application… don't do patch behaviour. Thank you McSink!
- pLoadSegCalledFromOwnApp = false;
- SetA5(A5RegisterOnEntry);
- }
- else
- {
- pLoadSegCalledFromOwnApp = true;
- pOldResFile = MAUseResFile(gCodeRefNum);// Must set a global because we return
- // from this function and then forward to
- // the actual segment loader which should
- // also be pointing to the _now_ correct
- // resfile. When we get called back again
- // in PostLoadMacAppSegment we will
- // restore the old resFile as the current
- // resFile. Sorry about the global.
-
- if (!PreloadSegmentResource(segnum))
- {
- #if qDebug
- GetCallersMethodName(s);
- SetResLoad(false);
- seg = MAGet1Resource(kCode, segnum);
-
- GetResInfo(seg, &id, &kind, segName);
- SetResLoad(true);
- //###SRF ProgramBreak("In " + s + form(" couldn't load segment: %d", segnum) + segName);
- #endif
-
- Failure(memFullErr, 0);
- }
-
- (*gIsLoadedSeg)[segnum - 1] = true;
-
- #if qDebug
- if (gSegReport)
- {
- GetResInfo((*gCodeSegs)[segnum - 1], &id, &kind, segName);
- fprintf(stderr, " *** Segment Loaded: %d %s\n", segnum, (char *) segName);
- }
- #endif
-
- }
-
- return loadMacAppSegment;
- } // LoadMacAppSegment
-
- #pragma pop
- #endif
-
- //----------------------------------------------------------------------------------------
- // LoadResidentSegments:
- //----------------------------------------------------------------------------------------
- #if !qPowerPC
- #pragma segment MAMemoryRes
- // Must be in Main segment
-
- void LoadResidentSegments()
- {
- short offset,
- segnum,
- rsrcCnt;
- Handle nameList, seg;
- SignedBytePtr p;
- CStr255 name;
- ResType theType;
- char savedState;
-
- rsrcCnt = CountResources('res!');
- for (short resIndex = 1; resIndex <= rsrcCnt; ++resIndex)
- {
- nameList = GetIndResource('res!', resIndex);
- savedState = HGetState(nameList);
- HNoPurge(nameList);
-
- offset = 2;
- short numNames = *((IntegerPtr) * nameList);
- for (short i = 1; i <= numNames; ++i)
- {
- p = (SignedBytePtr)(*nameList + offset);
- BlockMove(p, &name, *p + 1);
- offset += name.Length() + 1;
-
- seg = MAGet1NamedResource(kCode, name);
-
- if (seg)
- {
- GetResInfo(seg, &segnum, &theType, name);
- #ifdef __MWERKS__
- if (IsHandleLocked(seg)) // if its locked, then jump table is already set up
- (*gIsResidentSeg)[segnum - 1] = true;
- else
- #endif
- SetResidentSegment(segnum, true);
- }
- }
-
- HSetState(nameList, savedState);
- ReleaseResource(nameList);
- }
- } // LoadResidentSegments
- #endif
-
- //----------------------------------------------------------------------------------------
- // MemSpaceIsLow:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Boolean MemSpaceIsLow()
- {
- BuildAllReserves();
- return IsHandlePurged(pMemReserve);
- } // MemSpaceIsLow
-
- //----------------------------------------------------------------------------------------
- // NewPermHandle:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Handle NewPermHandle(Size logicalSize)
- {
- static const short initVal = 0xF3; // odd at all byte boundaries
-
- Boolean priorPerm;
- Handle aHandle;
-
- priorPerm = PermAllocation(true);
- aHandle = NewHandle(logicalSize);
- pPermAllocation = priorPerm;
- FailNIL(aHandle);
- #if qDebug
- BlockSet(*aHandle, logicalSize, initVal);
- #endif
- return aHandle;
- } // NewPermHandle
-
- //----------------------------------------------------------------------------------------
- // NewPermPtr:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Ptr NewPermPtr(Size logicalSize)
- {
- static const short initVal = 0xF3; // odd at all byte boundaries
-
- Boolean priorPerm;
- Ptr aPtr;
-
-
- priorPerm = PermAllocation(true);
- aPtr = NewPtr(logicalSize);
- pPermAllocation = priorPerm;
- FailNIL(aPtr);
- #if qDebug
- BlockSet(aPtr, logicalSize, initVal);
- #endif
- return aPtr;
- } // NewPermPtr
-
- //----------------------------------------------------------------------------------------
- // PermAllocation:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Boolean PermAllocation(Boolean permanent)
- {
- Boolean permAllocation = pPermAllocation;
-
- if (permanent != pPermAllocation)
- {
- pPermAllocation = permanent;
- if (permanent)
- BuildCodeReserve(kGZMaxAlloc, false);
- }
-
- return permAllocation;
- } // PermAllocation
-
- //----------------------------------------------------------------------------------------
- // PermHandToHand:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- void PermHandToHand(Handle& theHndl)
- {
- Boolean priorPerm;
- OSErr err;
-
- priorPerm = PermAllocation(true);
- err = HandToHand(&theHndl);
- pPermAllocation = priorPerm;
-
- FailOSErr(err);
-
- } // PermHandToHand
-
-
- //========================================================================================
- // struct CWithCodeResFileDo
- //========================================================================================
-
- struct CWithCodeResFileDo
- {
- public:
- short &fSegNum;
- Handle &fSeg;
-
- CWithCodeResFileDo(short &segnum,
- Handle &seg)
- :
- fSegNum(segnum),
- fSeg(seg)
- {
- }
- };
-
- //----------------------------------------------------------------------------------------
- // DoGetSegHandle:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- void DoGetSegHandle(void* scopeLink)
- {
- CWithCodeResFileDo* segInfo = (CWithCodeResFileDo*)scopeLink;
-
- short saveResLoad = LMGetResLoad();
- SetResLoad(true); // yes, we really *do* want it.
- segInfo->fSeg = Get1Resource(kCode, segInfo->fSegNum);
- SetResLoad(saveResLoad);
- } // DoGetSegHandle
-
-
- //========================================================================================
- // GLOBAL Procedures
- //========================================================================================
- #undef Inherited
-
- //----------------------------------------------------------------------------------------
- // PreloadSegmentResource:
- //----------------------------------------------------------------------------------------
- #if !qPowerPC
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- pascal Boolean PreloadSegmentResource(short segnum)
- {
- Handle seg;
- CWithCodeResFileDo scopeLink(segnum, seg);
-
- #if qDebug
- if (pPermAllocation)
- {
- if (!((*gIsResidentSeg)[segnum - 1]))
- {
- fprintf(stderr, "segment # = %d\n", segnum);
- ProgramBreak("Trying to load a segment with PermAllocation == true.");
- }
- }
- #endif
-
- WithCodeResFileDo(&DoGetSegHandle, &scopeLink);
-
- if (!seg)
- return false;
- else
- {
- if (!IsHandleLocked(seg)) // not yet locked
- LockHandleHigh(seg);
- HNoPurge(seg);
- return true;
- }
- } // PreloadSegmentResource
- #endif
-
- //----------------------------------------------------------------------------------------
- // ScanList:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- typedef Handle *HandlePtr;
-
- void ScanList(HandleListHandle list,
- DoToHandlesType DoToHandle,
- void *scopeLink)
- {
- HandlePtr p = (HandlePtr) * list;
-
- for (short i = (short)(GetHandleSize((Handle)list) / sizeof(Handle)); i > 0; --i, ++p)
- {
- DoToHandle(*p, scopeLink);
- }
- } // ScanList
-
-
- //----------------------------------------------------------------------------------------
- // ScanHandles:
- //----------------------------------------------------------------------------------------
- void ScanHandles(DoToHandlesType DoToHandle,
- void *staticLink)
- {
- #if !qPowerPC
- ScanList(gCodeSegs, DoToHandle, staticLink);
- #endif
-
- if (gApp1MemList)
- ScanList(gApp1MemList, DoToHandle, staticLink);
- ScanList(gSysMemList, DoToHandle, staticLink);
- if (gApp2MemList)
- ScanList(gApp2MemList, DoToHandle, staticLink);
- } // ScanHandles
-
- //----------------------------------------------------------------------------------------
- // SetPermHandleSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- void SetPermHandleSize(Handle h, Size newSize)
- {
- static const short initVal = 0xF3;
-
- Boolean priorPerm;
- #if qDebug
- Size oldSize;
- #endif
-
- priorPerm = PermAllocation(true);
- #if qDebug
- oldSize = GetHandleSize(h);
- #endif
-
- SetHandleSize(h, newSize);
- pPermAllocation = priorPerm; // Since we are in the memory unit we can break
- // the encapsulation of the PermAllocation Call to
- // just set the pPermAllocation flag back
- // directly. This lets us be assured that no
- // operations have occurred that would invalidate
- // the MemErr flag thus the following call will
- // give a true result
- FailMemError();
- #if qDebug
- if (oldSize < newSize)
- BlockSet((Ptr) * h + oldSize, newSize - oldSize, initVal);
- #endif
-
- } // SetPermHandleSize
-
- //----------------------------------------------------------------------------------------
- // SetPermPtrSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- void SetPermPtrSize(Ptr p, Size newSize)
- {
- static const short initVal = 0xF5;
-
- Boolean priorPerm;
- #if qDebug
- Size oldSize;
- #endif
-
- priorPerm = PermAllocation(true);
- #if qDebug
- oldSize = GetPtrSize(p);
- #endif
-
- SetPtrSize(p, newSize);
- pPermAllocation = priorPerm; // Since we are in the memory unit we can break
- // the encapsulation of the PermAllocation Call to
- // just set the pPermAllocation flag back
- // directly. This lets us be assured that no
- // operations have occurred that would invalidate
- // the MemErr flag thus the following call will
- // give a true result
- FailMemError();
- #if qDebug
- if (oldSize < newSize)
- BlockSet((Ptr)p + oldSize, newSize - oldSize, initVal);
- #endif
-
- } // SetPermPtrSize
-
- //----------------------------------------------------------------------------------------
- // SetReserveSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- void SetReserveSize(Size forCode, Size forOther)
- {
- #if !qPowerPC
- pSzCodeReserve = forCode;
- #endif
- pSzMemReserve = forOther;
-
- // Since the numbers have changed, make sure we start from scratch.
- pReserveExists = false;
- EmptyHandle(pMemReserve);
-
- BuildAllReserves();
- } // SetReserveSize
-
- //----------------------------------------------------------------------------------------
- // SetResidentSegment:
- //----------------------------------------------------------------------------------------
- #if !qPowerPC
- #pragma segment MAMemoryRes
-
- // must be in Main segment
-
- void SetResidentSegment(short segnum, Boolean makeResident)
- {
- #if qDebug
- short id;
- ResType kind;
- CStr255 segName;
- MAName s;
- Handle seg;
- #endif
-
- if (makeResident)
- {
- (*gIsResidentSeg)[segnum - 1] = true;
- if (!PreloadSegment(segnum))
- {
- #if qDebug
- GetCallersMethodName(s);
- SetResLoad(false);
- seg = MAGet1Resource(kCode, segnum);
- SetResLoad(true);
- GetResInfo(seg, &id, &kind, segName);
- //###SRF ProgramBreak("In " + s + form(" couldn't load segment: %d", segnum) + segName);
- #endif
-
- Failure(memFullErr, 0);
- }
- }
- else
- (*gIsResidentSeg)[segnum - 1] = false;
- } // SetResidentSegment
-
- #endif
-
- //----------------------------------------------------------------------------------------
- // SetStackSpace:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMiniInit
-
- void SetStackSpace(long numBytes)
- {
- long newLimit;
-
- // Make sure numBytes is even
- if (odd(numBytes)) numBytes++;
-
- newLimit = (long)LMGetCurStackBase() - numBytes;
- if ((long)GetApplLimit() > newLimit)
- SetApplLimit((Ptr)newLimit);
- } // SetStackSpace
-
- //--------------------------------------------------------------------------------------------------
-
- class CTotalTempSize
- {
- public:
- Boolean &fJustLocked;
- Handle &fCanPurge;
- Size &fTotal;
- THz &fApplZone;
-
- CTotalTempSize(Boolean &justLocked,
- Handle &canPurge,
- Size &total,
- THz &applZone)
- :
- fJustLocked(justLocked),
- fCanPurge(canPurge),
- fTotal(total),
- fApplZone(applZone)
- {
- }
- };
-
-
- //----------------------------------------------------------------------------------------
- // CTotalTempSize::TotalUp:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- void TotalUpHandleList(Handle h, void* staticLink)
- {
- CTotalTempSize* tempInfo = (CTotalTempSize*)staticLink;
- Boolean hIsLocked;
-
- if (h != 0 && !IsHandlePurged(h)) // in memory already
- if (HandleZone(h) == tempInfo->fApplZone) // in application heap
- {
- HNoPurge(h);
-
- hIsLocked = IsHandleLocked(h);
-
- if (!tempInfo->fJustLocked || hIsLocked)
- tempInfo->fTotal += GetHandleSize(h) + 8;
- // add in the size plus heap overhead
-
- if (!hIsLocked)
- if (tempInfo->fCanPurge == NULL)
- if (IsHandleEligible(h))
- tempInfo->fCanPurge = h;
- }
- } // TotalUpHandleList
-
-
- //========================================================================================
- // GLOBAL Procedures
- //========================================================================================
- #undef Inherited
-
- //----------------------------------------------------------------------------------------
- // TotalTempSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- Size TotalTempSize(Boolean justLocked,
- Handle &canPurge)
- {
- Size total;
- THz applZone;
- CTotalTempSize scopeLink(justLocked, canPurge, total, applZone);
-
- canPurge = NULL;
- total = 0;
- applZone = ApplicationZone();
-
- ScanHandles(& TotalUpHandleList, &scopeLink);
-
- return total;
- } // TotalTempSize
-
- //----------------------------------------------------------------------------------------
- // WithCodeResFileDo:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
-
- void WithCodeResFileDo(DoWithResFileType DoWithResFile,
- void *scopeLink)
- {
- short oldResFile = MAUseResFile(gCodeRefNum);
-
- DoWithResFile(scopeLink);
-
- MAUseResFile(oldResFile);
- } // WithCodeResFileDo
-
- #if !qPowerPC
- #if qDebug
-
- //----------------------------------------------------------------------------------------
- // CheckCallChain:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- void CheckCallChain(const CStackFrame& frame, void* /* staticLink */)
- {
- void *pc = frame.GetReturnAddress();
-
- short itsSeg = GetSegFromPC(pc);
- if ((itsSeg != 0) &&!(*gIsResidentSeg)[itsSeg - 1] && (*gIsLoadedSeg)[itsSeg - 1])
- {
- fprintf(stderr, "Segment#: %d\n", itsSeg);
- ProgramBreak("I really don't think that you want to unload a segment into which you are going to return!");
- }
- } // CheckCallChain
-
- #endif
- #endif
-
- //========================================================================================
- // GLOBAL Procedures
- //========================================================================================
- #undef Inherited
-
- //----------------------------------------------------------------------------------------
- // IsModelFarCodeSegment:
- //----------------------------------------------------------------------------------------
- #if !qPowerPC
- #pragma segment MAMemoryRes
-
- inline Boolean IsModelFarCodeSegment(Handle seg)
- {
- if (seg)
- return **((unsigned short **) seg) == 0xFFFF;
- else
- return false;
- } // IsModelFarCodeSegment
- #endif
-
-
- // must be in Main segment
-
- #if !qPowerPC
- struct ModelFarCodeHeader
- {
- short field1;
- short field2;
- long A5OffsetOf16BitEntries;
- long numOf16BitEntries;
- long A5OffsetOf32BitEntries;
- long numOf32BitEntries;
- char otherEvenMorePrivateStuff; // You didn't think I would reveal any more
- // than I had to did you?
- };
-
- typedef ModelFarCodeHeader *ModelFarCodeHeaderPtr,
- **ModelFarCodeHeaderHandle;
- #ifdef __MWERKS__
- const short kJTSkipOver = 4; //for large model, CW looks at the 2nd long in the resource
- #else
- const short kJTSkipOver = 2; // size of jmp (or loadseg) instruction
- // that must be skipped in the JT Entry in
- // order to get to the target address
- #endif
- #endif
-
- //----------------------------------------------------------------------------------------
- // DoUnloadAllSegments:
- //----------------------------------------------------------------------------------------
- #if !qPowerPC
-
- void DoUnloadAllSegments(void* scopeLink)
- {
- long* jmpTablePtr = (long*)scopeLink;
- short i;
- Handle seg;
- for (i = 0; i < pMaxSegNum; ++i)
- {
- if (!(*gIsResidentSeg)[i] && (*gIsLoadedSeg)[i])
- {
- seg = (*gCodeSegs)[i];
- if ((seg) && !IsHandlePurged(seg))
- {
- if (IsModelFarCodeSegment(seg))
- {
- if ((*((ModelFarCodeHeaderHandle)seg))->numOf16BitEntries)
- UnloadSeg((Ptr)(*jmpTablePtr + (*((ModelFarCodeHeaderHandle) seg))->
- A5OffsetOf16BitEntries + kJTSkipOver));
- else // Has to be the other since we wouldn't even
- // have a segment otherwise
- UnloadSeg((Ptr)(*jmpTablePtr + (*((ModelFarCodeHeaderHandle)seg))->
- A5OffsetOf32BitEntries + kJTSkipOver));
- }
- else
- {
- #ifdef __MWERKS__
- long firstProcInSegment = (*(long*)((*seg) + kJTSkipOver)) + (long) GetA5();
- UnloadSeg((Ptr)firstProcInSegment);
-
- #else
- UnloadSeg((Ptr)(*jmpTablePtr + **((IntegerHandle)seg) + kJTSkipOver));
- #endif
-
- }
- HNoPurge(seg);
- (*gIsLoadedSeg)[i] = false;
- }
- }
- }
- } // DoUnloadAllSegments
-
- #endif
-
- //========================================================================================
- // GLOBAL Procedures
- //========================================================================================
- #undef Inherited
-
- //----------------------------------------------------------------------------------------
- // UnloadAllSegments:
- //----------------------------------------------------------------------------------------
- #if !qPowerPC
- #pragma segment MAMemoryRes
- // must be in Main segment
-
- void UnloadAllSegments()
- {
- #if qDebug
- if (gCheckRsrcUsage)
- CheckRsrcUsage();
- #endif
-
- if (gUnloadAllSegs)
- {
- #if qDebug
- CStackFrame stackFrame((void *) GetCurStackFramePtr());
- EachFrameDo(stackFrame, &CheckCallChain, (void*)kNoStaticLink);
- #endif
-
- long jmpTablePtr = (long) (GetA5() + LMGetCurJTOffset());
- WithCodeResFileDo(&DoUnloadAllSegments, &jmpTablePtr);
-
- if (gSegReport)
- ProgramReport(" *** Just unloaded all segments ***", gMemMgtBreak);
- }
- } // UnloadAllSegments
-
- #endif
-
- //----------------------------------------------------------------------------------------
- // WriteReserves: fprintf's the temporary reserve and low-memory reserves to stderr
- //----------------------------------------------------------------------------------------
-
- #if qDebug
-
- #pragma segment MADebug
-
- void WriteReserves()
- {
- WrLblPtr("Temporary reserve (pCodeReserve)", (long)pCodeReserve);
- fprintf(stderr, "\n");
- WrLblPtr("Low-memory reserve (pMemReserve)", (long)pMemReserve);
- fprintf(stderr, "\n");
- } // WriteReserves
-
- #endif
-
-